#include "../include/Tool.h"
#include <sys/timeb.h>
#include <sys/time.h>
extern "C" {
    #include <execinfo.h>
    #include "zlib.h"
}

namespace ZY {

    Tool::Tool()
    {
        //ctor
    }

    Tool::~Tool()
    {
        //dtor
    }


    uint64_t Tool::ntohl64(uint64_t arg64)
    {
      uint64_t res64;

    #if __BYTE_ORDER==__LITTLE_ENDIAN
          uint32_t low = (uint32_t) (arg64 & 0x00000000FFFFFFFFLL);
          uint32_t high = (uint32_t) ((arg64 & 0xFFFFFFFF00000000LL) >> 32);

          low = ntohl(low);
          high = ntohl(high);

          res64 = (uint64_t) high + (((uint64_t) low) << 32);
    #else
          res64 = arg64;
    #endif

      return res64;
    }

    string & Tool::stringAppend( string & str1 , const int num )
    {
        char buff[16];
        int n;
        n = sprintf( buff , "%d" , num );
        return str1.append( buff , n );
    }

    string & Tool::stringAppend( string & str1 , const unsigned int num )
    {
        char buff[16];
        int n;
        n = sprintf( buff , "%ud" , num );
        return str1.append( buff , n );
    }


    string & Tool::stringAppend( string & str1 , const int64_t num )
    {
        char buff[24];
        int n;
        n = sprintf( buff , "%lld" , (long long int) num );
        return str1.append( buff , n );
    }

    string & Tool::stringAppend( string & str1 , const uint64_t num )
    {
        char buff[24];
        int n;
        n = sprintf( buff , "%llud" , (unsigned long long int) num );
        return str1.append( buff , n );
    }

    int Tool::explode( vector<string> &ret , const char *c , const char *str )
    {
        int n = 0 , len = strlen(str);

        char t_str[ len + 1 ];
        strcpy( t_str , str );
        char *cr = strtok( (char*) t_str , c );

        ret.clear();

        while( cr != NULL ) {
            string tstr( cr );
            ret.push_back( cr );
            cr = strtok( NULL , c );
            n ++;
        }

        return n;
    }

    int Tool::implode( string & ret , string &c , vector<string> &str_vec )
    {
        int n = str_vec.size() ;
        ret.clear();
        for( int i = 0 ; i < n ; i ++ ) {
            string & str = str_vec[i];
            if ( i > 0 ) {
                ret.append( c );
            }
            ret.append( str );
        }
        return n;
    }

    int Tool::implode( string & ret , char *c , vector<char*> &str_vec )
    {
        int n = str_vec.size() ;
        ret.clear();
        for( int i = 0 ; i < n ; i ++ ) {
            string str(str_vec[i]);
            if ( i > 0 ) {
                ret.append( c );
            }
            ret.append( str );
        }
        return n;
    }


    //下标为返回值，值为机率
    int Tool::getRandFromLst( int perMap[] , int num )
    {
        int totalPercent , i , tmpInt ;
        int data[ num ];
        totalPercent = 0;

        memcpy( data , perMap , num * sizeof( int ) );

        for( i = 0 ; i < num ; i ++ ) {
            tmpInt = data[i];
            data[i] += totalPercent;
            totalPercent += tmpInt;
        }

        tmpInt = getRand( 1 , totalPercent );
        for( i = 0 ; i < num ; i ++ ) {
            if ( tmpInt <= data[i] ) {
                return i;
            }
        }
        return num - 1 ;
    }

    double Tool::microtime()
    {
//        timeb t;
//        ftime( & t );
//        return 1000 * t.time + t.millitm;
        double retTime , usec;
        struct timeval timeval_t;

        gettimeofday ( & timeval_t , NULL );
        retTime = timeval_t.tv_sec;
        usec = timeval_t.tv_usec;
        usec /= 1000000;
        retTime += usec;
        return retTime;

    }

    time_t Tool::getLocalTime( time_t tt )
    {
        if ( tt == 0 ) {
            time( & tt );
        }

        struct tm *t;

        t = localtime( & tt );

        return mktime( t );
    }

    string Tool::dateTime()
    {
        struct tm *t;
        time_t tt;
        time( & tt );
        t = localtime( & tt );

        char buff[128];

        size_t s = strftime( buff , sizeof( buff ) , "%Y-%m-%d %H:%M:%S" , t );

        string str( buff , s );

        return str;
    }

    void Tool::toUpper( string & s )
    {
        unsigned long len = s.length();
        char buff[ len + 1];
        const char *sp = s.c_str();

        for( unsigned int i = 0 ; i < len ; i ++ ) {
            buff[i] = toupper( sp[i] );
        }

        string str( buff , len );
        s.swap( str );
    }

    void toLower( string & s )
    {
        unsigned long len = s.length();
        char buff[ len + 1];
        const char *sp = s.c_str();

        for( unsigned int i = 0 ; i < len ; i ++ ) {
            buff[i] = tolower( sp[i] );
        }

        string str( buff , len );
        s.swap( str );
    }

    //获取一个随机数，为[min,max]闭区间内的一个整数1
     int Tool::getRand( int min , int max )
    {
        int i;
        int ret;

        if ( min == max ) {
            return min;
        } else if ( min > max ) {
            return -1;
        }

        srand( ( unsigned long int ) ( microtime() * 1000000 ) );
        i = max - min + 1;
        if ( i < 0 ) {
            return -1;
        }

        ret= min + ( (unsigned int)( rand() * ( microtime() - time( NULL ) ) * 1000000 ) ) % i ;
        if ( ret < min ) {
            ret = min;
        }
        if ( ret > max ) {
            ret = max;
        }

        return ret;
    }

    //获取一个随机数，为[min,max]闭区间内的一个整数1
     int64_t Tool::getRand( int64_t min , int64_t max )
    {
        int64_t i;

        if ( min == max ) {
            return min;
        } else if ( min > max ) {
            return -1;
        }

        srand( ( unsigned long int ) ( microtime() * 1000000 ) );
        i = max - min + 1;
        if ( i < 0 ) {
            return -1;
        }

        return min + ( (uint64_t)( rand() * ( microtime() - time( NULL ) ) * 1000000000000000000 ) ) % i ;
    }

    string Tool::getCalltrac()
    {
        char buff[4096];
        size_t s = getCalltrac( buff );
        string str( buff , s );
        return str;
    }

    size_t Tool::getCalltrac( char *buff )
    {
        bzero( buff , sizeof( buff ) );

        void *array[10];
        size_t size;
        char **strings , *msg;
        size_t n , f , offset = 0;
        unsigned i , t ;
        size = backtrace( array , 10 );
        strings = backtrace_symbols( array , size );

        for( i = size -1 ; i > 0 ; i -- ) {
            msg = strings[i];
            n = strlen( msg );
            f = 0;
            for( t = 0 ; t < n ; t ++ ) {
                if ( msg[t] == '(' ) {
                    f = 1;
                    continue;
                }
                if ( msg[t] == ')' ) {
                    buff[offset ++ ] = '/';
                    break;
                }
                if ( f == 1 ) {
                    buff[ offset ++ ] = msg[t];
                }
            }
        }
        free( strings );
        buff[offset] = 0;
        return offset;
    }



char * Tool::getFileName( char *arg0 )
{
    static char filename[50];
    int i;
    for( i = strlen( arg0 ) - 1 ; i >= 0 ; i -- )
    {
        if ( arg0[i] == '/' ) {
            break;
        }
    }

    strcpy( filename , arg0 + i + 1 );
    return filename;
}

    /**
       检查唯一性运行，如果发现有运行中的进程或其它错误，则返回false
    */
    bool  Tool::checkOnlyRun( const char *filename , const char *pidFile )
    {
        char val[1024] , buff[1024];
        int offset ,fd , n , pid ;
        FILE *fpin;
        //printf( "Load Pid File:%s\n" , pidFile );

        fd = open( pidFile , O_RDONLY | O_CREAT , 0666 );
        if ( fd == -1 ) {
            printf( "Open File Error:%s\n" , filename );
            return false;
        }
        val[0] = 0;
        offset = 0;
        while( 1 ) {
            n = read( fd , val , 1024 );

            if ( n == -1 ) {
                if ( errno == EINTR ) {
                    //因为出现信号而中断读取，所以继续
                    continue;
                } else {
                    ////printf( "Read Error:%d\n" , errno );
                    break;
                }
            } else if ( n == 0 ) {
                break;
            }

            val[n] = 0;
        }
        close( fd );

        //printf( "File COntent:%s\n" , val );

        if ( strlen( val ) > 0  ) {
            //说明内容不为空，判断该pid是否存在
            pid = atoi( val );

            //top -b -n1 | grep '^\s*9360' -c
            //printf( "PHP CMD:%s\n", buff );
            //sprintf( buff , "top -b -n1 | grep '^\s*%d' -c" , pid );
            //sprintf( buff , "top -b -n 1 -p %d | grep '^\s*[0-9]' -c" , pid );
            sprintf( buff , "top -b -n 1 -p %d | grep '%s' -c" , pid , filename );
            if (( fpin = popen( buff , "r" )) == NULL ) {
                printf("popen error\n");
//                exit(0);
                return false;
            }
            bzero( buff , 1024 );
            if ( (n = fread( buff, sizeof( char ) , 1024 , fpin) ) ) {
                buff[n] = 0;
//                printf("Result:%s\n" , buff );

            } else {
//                printf("Exec failed.\n"  );
            }
            pclose( fpin );

            n = atoi( buff );

            if ( n > 0 ) {
                //进程正在运行中，退出
                printf( "Anthor Game is Running.Exit...\n");
                close( fd );
                //LogExitInfo( "Anthor Game is Running.Exit..." );
//                exit(0);
                return false;
            }

        }

        fd = open( pidFile , O_RDWR | O_CREAT | O_TRUNC , 0666 );
        //接管，写入自己的pid
        pid = getpid();
//        printf( "PID:%d\n" , pid );
        sprintf( val , "%d" , pid );
        write( fd , val , strlen( val ) );

        close( fd );

        return true;
    }

    map< string , string > Tool::getHttpRespondHeaderMap( string headerStr )
    {
        //解析头
        vector<string> lines , s;
        map< string , string > header;
        Tool::explode( lines , "\r\n" , headerStr );
        //解析状态
        Tool::explode( s , " " , lines[0] );
        header["success_code"] = s[1];
        for( unsigned int i = 1 ; i < lines.size() ; i ++ ) {
            Tool::explode( s , ": " , lines[i] );
            header[ s[0] ] = s[1];
            if ( s.size() > 2 ) {
                string &h = header[ s[0] ];
                for( unsigned int i = 2 ; i < s.size() ; i ++ ) {
                    h.append( " " );
                    h.append( s[i] );
                }
            }
        }

        return header;
    }

    string Tool::getDateTime()
    {
        time_t time_now;
        unsigned len;

        char timebuf[64]={0};
        time (&time_now);
        strcpy(timebuf,ctime(&time_now));
        len=strlen(timebuf);
        timebuf[len-1]='\0';

        string datetime( timebuf );

        return datetime;
    }

    void Tool::CompressSelf( string &str )
    {
        Tool::Compress( str , str );
    }

    string Tool::Compress( string &str )
    {
        string nstr;
        Tool::Compress( nstr , str );
        return nstr;
    }

    void Tool::Compress( string &des_str , string &src_str )
    {
        int src_len = src_str.length();
        uLongf len = src_len * 2;
        char *buff = new char[len];//从栈内存修改为堆内存，避免栈内存分配不成功时的断错误
        int n = compress( (Bytef *)buff , & len , (const Bytef*) src_str.c_str() , src_len );
        if ( n != 0 ) {
        }
        des_str.assign( buff , len );
        delete[] buff;
        //free(buff);
    }

    void Tool::unCompressSelf( string & str )
    {
        string des_str;
        Tool::unCompress( des_str , str );
        str.assign( des_str );
    }

    string Tool::unCompress( const string & str )
    {
        string nstr;
        Tool::unCompress( nstr , str );
        return nstr;
    }

    void Tool::unCompress( string &des_str , const string &src_str )
    {
        int src_len = src_str.length();

        if ( src_len <= 0 ) {
            des_str.assign( "" , 0 );
            return;
        }

        uLongf len = src_len * 10;

        if ( len < 4096 ) {
            len = 4096;
        }

        char *buff = new char[ len + 1];
        int n = uncompress( (Bytef *)buff , & len , (const Bytef*) src_str.c_str() , src_len );
        if ( n != 0 ) {
        }
        des_str.assign( buff , len );
        delete [] buff;
    }

    string Tool::toString( const int8_t v )
    {
        return toString( (const int ) v );
    }
    string Tool::toString( const short v )
    {
        return toString( (const int ) v );
    }
    string Tool::toString( const int v )
    {
        char buff[16];
        size_t n = sprintf( buff , "%d" , v );
        string str( buff , n );
        return str;
    }
    string Tool::toString( const int64_t v )
    {
        char buff[32];
        size_t n = sprintf( buff , "%lld" , ( long long int ) v );
        string str( buff , n );
        return str;
    }
    string Tool::toString( const double v )
    {
        char buff[64];
        size_t n = sprintf( buff , "%f" , v );
        string str( buff , n );
        return str;
    }
    string Tool::toString( const char *c)
    {
        string str( c , strlen( c ) );
        return str;
    }
    string Tool::toString( const char* c, size_t n)
    {
        string str( c , n );
        return str;
    }
    string Tool::toString( const string &str )
    {
        return str;
    }
}
